package http

import (
	"github.com/edgexfoundry/edgex-go/internal/app/core/metadata/application"
	"github.com/edgexfoundry/edgex-go/internal/app/dtos"
	"github.com/edgexfoundry/edgex-go/internal/app/dtos/responses"
	"github.com/edgexfoundry/edgex-go/internal/io"
	"github.com/edgexfoundry/edgex-go/internal/pkg"
	"github.com/edgexfoundry/edgex-go/internal/pkg/correlation"
	"github.com/edgexfoundry/edgex-go/internal/pkg/utils"
	"github.com/edgexfoundry/go-mod-bootstrap/v2/bootstrap/container"
	"github.com/edgexfoundry/go-mod-bootstrap/v2/di"
	"github.com/edgexfoundry/go-mod-core-contracts/v2/common"
	commonDTO "github.com/edgexfoundry/go-mod-core-contracts/v2/dtos/common"
	"net/http"
)

type DeviceProfileController struct {
	jsonDtoReader io.DtoReader
	yamlDtoReader io.DtoReader
	dic           *di.Container
}

// NewDeviceProfileController creates and initializes an DeviceProfileController
func NewDeviceProfileController(dic *di.Container) *DeviceProfileController {
	return &DeviceProfileController{
		jsonDtoReader: io.NewJsonDtoReader(),
		yamlDtoReader: io.NewYamlDtoReader(),
		dic:           dic,
	}
}

func (dc *DeviceProfileController) DeviceProfileAdd(w http.ResponseWriter, r *http.Request) {
	if r.Body != nil {
		defer func() { _ = r.Body.Close() }()
	}

	lc := container.LoggingClientFrom(dc.dic.Get)

	ctx := r.Context()
	correlationId := correlation.FromContext(ctx)

	var reqDTOs dtos.DeviceProfileAddRequest

	err := dc.jsonDtoReader.Read(r.Body, &reqDTOs)
	if err != nil {
		utils.WriteErrorResponse(w, ctx, lc, err, "")
		return
	}

	deviceId := reqDTOs.DeviceId

	var addDeviceProfileResponse interface{}
	reqId := reqDTOs.RequestId
	newId, err := application.DeviceProfileAdd(reqDTOs.Profile, ctx, dc.dic, deviceId)
	if err != nil {
		lc.Error(err.Error(), common.CorrelationHeader, correlationId)
		lc.Debug(err.DebugMessages(), common.CorrelationHeader, correlationId)
		addDeviceProfileResponse = commonDTO.NewBaseResponse(
			reqId,
			err.Message(),
			err.Code())
	} else {
		addDeviceProfileResponse = commonDTO.NewBaseWithIdResponse(
			reqId,
			"",
			http.StatusCreated,
			newId)
	}

	utils.WriteHttpHeader(w, ctx, http.StatusMultiStatus)
	pkg.EncodeAndWriteResponse(addDeviceProfileResponse, w, lc)
}

func (dc *DeviceProfileController) DeviceProfileById(w http.ResponseWriter, r *http.Request) {
	lc := container.LoggingClientFrom(dc.dic.Get)
	ctx := r.Context()

	// URL parameters
	deviceId := utils.ParseQueryStringToString(r, common.DeviceId, "")

	deviceProfile, err := application.DeviceProfileById(deviceId, ctx, dc.dic)
	if err != nil {
		utils.WriteErrorResponse(w, ctx, lc, err, "")
		return
	}

	dp := responses.ToDeviceProfileDTO(deviceProfile)

	response := responses.NewDeviceProfileResponse("", "", http.StatusOK, dp)
	utils.WriteHttpHeader(w, ctx, http.StatusOK)
	pkg.EncodeAndWriteResponse(response, w, lc) // encode and send out the response
}
